﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ScannerApp.Common.PLC
{
    public class DMTDeltaPLC 
    {
        private const int _conn_connNum = 0;   //通訊端口號，以太網固定爲0。
        private const int _commType = 1;   //通訊類型，0表示串口，1表示以太網。
        private const int _port = 502;

        private const int _stationNoReq = 0x01;  //發送數據的站號，固定。

        public const int _checkArea = 1002;    //PLC的M區編號，用於測試是否斷線。

        private const int MaxReadCount = 10;//允許讀寫的次數。

        private const int sendTimeout = 1000;    //發送數據的超時時間。單位:ms
        private const int recTimeout = 1000;    //接收數據的超時時間。單位:ms
        private static Object LockObject = new Object();    //該鎖對象控制不能同時讀寫PLC，且PLC在讀寫時，不能關閉PLC

        private static bool _IsConntect = false;
        public static bool IsConntect { get => _IsConntect; set => _IsConntect = value; }

        public static bool ConnPLC(string _ip)
        {
            lock (LockObject)
            {
                try
                {
                    IPAddress ipaddress = IPAddress.Parse(_ip);
                    int ipAddress = BitConverter.ToInt32(ipaddress.GetAddressBytes(), 0);

                    int status = DMT.OpenModbusTCPSocket(_conn_connNum, ipAddress);
                    if (status > 0)
                    {
                        IsConntect = true;
                        return true;
                    }
                    return false;
                }
                catch (Exception ex)
                {
                    return false;
                   // throw ex;
                }
            }
        }

        public static bool DisConnPLC()
        {
            lock (LockObject)
            {
                try
                {
                    DMT.CloseSocket(_conn_connNum);
                    return true;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

        public static bool CheckPLCStatus()
        {
            try
            {
                SetMReg(_checkArea, true);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static int SetDReg(int Reg, int RegValue)
        {
            int r = 0;
            lock (LockObject)
            {
                try
                {
                    StringBuilder req = new StringBuilder(1024);
                    StringBuilder res = new StringBuilder(1024);
                    int DV_AddD = DMT.DevToAddrW("DVP", "D" + Reg, 2); 
                    uint DV_CoverD = (uint)RegValue; 
                    int senddate16low = DMT.WriteSingleRegW(_commType, _conn_connNum, _stationNoReq, DV_AddD, DV_CoverD, req, res);
                     if (senddate16low > 0)
                    {
                        r = 1;
                    }
                    else r = 0;
                }
                catch (Exception ee)
                {
                    throw ee;
                }
            }



            return r;
        }

        public static int SetDDReg(int Reg, int RegValue)
        {
            int r = 0;
            lock (LockObject)
            {
                try
                {
                    StringBuilder req = new StringBuilder(1024);
                    StringBuilder res = new StringBuilder(1024);
                    int DV_AddD = DMT.DevToAddrW("DVP", "D" + Reg, 2);

                     uint DV_CoverD = (uint)RegValue;
                    uint XspeedH = DV_CoverD >> 16;
                    //uint XspeedL = (DV_CoverD << 16) >> 16;
                    //  UInt32 DV_StartOrder = UInt32.Parse(writeData);
                    int senddate16low = DMT.WriteSingleReg32W(_commType, _conn_connNum, _stationNoReq, DV_AddD, DV_CoverD, req, res);
                   //int senddate16hig = DMT.WriteSingleReg32W(_commType, _conn_connNum, _stationNoReq, DV_AddD+1, XspeedH, req, res);
                    if (senddate16low > 0)
                    {
                        r = 1;
                    }
                    else r = 0;
                }
                catch (Exception ee)
                {
                    throw ee;
                }
            }




            return r;
        }

        public static int ReadDReg(int Reg, out double RegValue)
        {
            int r = 0; RegValue = 0;
            lock (LockObject)
            {
                try
                {
                    StringBuilder req = new StringBuilder(1024);
                    StringBuilder res = new StringBuilder(1024);
                    int DV_AddD = DMT.DevToAddrW("DVP", "D" + Reg, 2);

                    uint[] DV_StartOrder = new uint[2];
                    // if (RegState) writeData = 1;
                    //  UInt32 DV_StartOrder = UInt32.Parse(writeData);
                    int senddate = DMT.ReadHoldRegsW(_commType, _conn_connNum, _stationNoReq, DV_AddD, 2, DV_StartOrder, req, res);
                    if (senddate > 0)
                    {
                        r = 0;
                        RegValue = float.Parse( DV_StartOrder[0].ToString());
                    }
                    else r = -1;
                }
                catch (Exception ee)
                {
                    throw ee;
                }
            }

            
            return r;
        }

        public static int ReadDDReg(int Reg, out double RegValue)
        {
            int r = 0;

            RegValue = 0;
            return r;
        }
        public static int SetMReg(int Reg,   bool RegState)
        {
            int r = 0; 
            lock (LockObject)
            {
                try
                {
                    StringBuilder req = new StringBuilder(1024);
                    StringBuilder res = new StringBuilder(1024);
                    int DV_AddM = DMT.DevToAddrW("DVP", "M" + Reg, 2);

                    UInt32 writeData = 0;
                    if (RegState) writeData = 1;
                   //  UInt32 DV_StartOrder = UInt32.Parse(writeData);
                    int senddate = DMT.WriteSingleCoilW(_commType, _conn_connNum, _stationNoReq, DV_AddM, writeData, req, res);
                    if (senddate > 0)
                    {
                        r= 1; 
                    }
                    else r= 0;
                }
                catch (Exception ee)
                {
                    throw ee;
                }
            }
            return r;
        }

        public static  int ReadMReg(int Reg, out bool RegState)
        {
            int r = 0; RegState = false;
            lock (LockObject)
            {
                try
                {
                    StringBuilder req = new StringBuilder(1024);
                    StringBuilder res = new StringBuilder(1024);
                    int DV_AddM = DMT.DevToAddrW("DVP", "M" + Reg, 2);

                    uint[] DV_StartOrder = new uint[1];
                    //  UInt32 DV_StartOrder = UInt32.Parse(writeData);
                    int senddate = DMT.ReadCoilsW(_commType, _conn_connNum, _stationNoReq, DV_AddM, 2, DV_StartOrder, req, res);
                    if (senddate > 0)
                    {
                      string rs = DV_StartOrder[0].ToString();
                         if (rs == "1")  RegState = true;
                        r = 1;
                          
                    }
                    else r = 0;
                }
                catch (Exception ee)
                {
                    throw ee;
                }
            }
           // RegState = false;
            return r;
        }

        
    }
}
